#pragma once
#include "logMessage.hpp"
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>

#include "ThreadPool.hpp"
#include "Task.hpp"
namespace Server
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };

    using namespace std;

    static const uint16_t gport = 8080;
    static const uint16_t gbacklog = 5;

    class tcpServer;
    class ThreadData
    {
    public:
        ThreadData(tcpServer* self,int sockfd)
            :self_(self),sockfd_(sockfd)
        {}
    public:
        tcpServer* self_;
        int sockfd_;
    };


    class tcpServer
    {
    public:
        tcpServer(const uint16_t &port = gport)
            : listen_sockfd_(-1), port_(port)
        {
        }

        void InitServer()
        {
            // 1.创建socket
            listen_sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
            if (listen_sockfd_ < 0)
            {
                logMessage(FATAL, "create socket error");
                exit(SOCKET_ERR);
            }
            logMessage(NORMAL, "create socket success");

            // 2.bind网络信息
            struct sockaddr_in local;
            memset(&local,0,sizeof(local));
            local.sin_family=AF_INET;
            local.sin_port=htons(port_);
            local.sin_addr.s_addr=INADDR_ANY;
            if(bind(listen_sockfd_,(struct sockaddr*)&local,sizeof(local))<0)
            {
                logMessage(FATAL,"bind socket error");
                exit(BIND_ERR);
            }

            logMessage(NORMAL,"bind socket success:%d",listen_sockfd_);
            
            //3.设置socket为监听状态
            if(listen(listen_sockfd_,gbacklog)<0)
            {
                logMessage(FATAL,"listen socket error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL,"listen socket success");

        }
        void start()
        {
            //初始化线程池
            ThreadPool<Task>::GetInstance()->run();
            logMessage(NORMAL,"Thread init success");
            //signal(SIGCHLD,SIG_IGN);
            for(; ;)
            {
                //4.server获取新链接
                struct sockaddr_in peer;
                socklen_t len=sizeof(peer);
                //sock:和客户端通信的文件描述符
                int sock=accept(listen_sockfd_,(struct sockaddr*)&peer,&len);
                if(sock<0)//没有获取新链接成功就执行下一次循环
                {
                    logMessage(FATAL,"accpect sock error");
                    continue;
                }
                logMessage(NORMAL,"accept sock success,get new sock:%d",sock);
                

                //5.通信就用sock文件描述符，面向字节流，后续都是文件操作
                /******************************version1*/
                // serverIO(sock);
                // close(sock);

                // /***************************version2多进程版*/
                // pid_t id=fork();
                // if(id==0)//子进程
                // {
                //     close(listen_sockfd_);
                //     //if(fork()>0 )exit(0);//也可以用信号
                //     //孙子进程
                    
                //     serverIO(sock);
                //     close(sock);
                //     exit(0);//变成孤儿进程，被os回收
                // }
                // //细节：父进程必须关闭子进程的sock，避免一直被占用
                // //这里的关闭并不是完全关闭，只是引用计数减一
                // close(sock);//获取之后立马关闭，多次链接出现sock都一样，也可能不一样

                // //父进程
                // // pid_t ret=waitpid(id,nullptr,0);
                // // if(ret>0)
                // // {
                // //     std::cout<<"waitsuccess"<<ret<<endl;
                // // }

                /********************************version3：多线程版本*/
                // pthread_t tid;
                // ThreadData* td=new ThreadData(this,sock);
                // pthread_create(&tid,nullptr,threadRoutinue,td);


                /*********************************vesion4:线程池版本*/

                //ThreadPool<Task>::GetInstance()->push(Task(sock,serverIO));
                
                //开始start的时候run
                ThreadPool<Task>::GetInstance()->push(Task(sock,serverIO));
            }
        }
        // static void* threadRoutinue(void* args)
        // {
        //     pthread_detach(pthread_self());
        //     ThreadData* td= static_cast<ThreadData*>(args);
        //     td->self_->serverIO(td->sockfd_);
        //     close(td->sockfd_);
        //     delete td; 
        //     return nullptr;
        // }

        
        ~tcpServer()
        {
        }

    private:
        int listen_sockfd_;//不负责通信，只负责监听链接，获取新链接
        uint16_t port_;
    };
}